package com.travelsky.flash.impl;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

import org.springframework.stereotype.Service;
import org.tmatesoft.svn.core.SVNDepth;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.wc.SVNClientManager;
import org.tmatesoft.svn.core.wc.SVNRevision;

import com.travelsky.flash.api.IProcessWar;
import com.travelsky.flash.constant.ServiceDeployConfigConstant;
import com.travelsky.flash.util.BaseUtil;
import com.travelsky.flash.util.DateUtil;
import com.travelsky.flash.util.SSHExecUtil;
import com.travelsky.flash.util.SvnKitUtil;
import com.travelsky.flash.util.WarUtil;
import com.travelsky.flash.util.handler.UpdateEventHandler;
import com.travelsky.flash.util.log.FlashLogger;
import com.travelsky.flash.vo.DestinationHostVO;
import com.travelsky.flash.vo.FileMoveOrCopyVO;
import com.travelsky.flash.vo.HostAccessVO;
import com.travelsky.flash.vo.SVNConfigVO;
import com.travelsky.flash.vo.SourceHostVO;

@Service
public class ProcessWarImpl implements IProcessWar {

	private static FlashLogger logger = new FlashLogger(ProcessWarImpl.class);
	
	// 创建一个可缓存的线程池
	private static Executor executor = Executors.newCachedThreadPool();

	@Override
	public int svnCheckOut(SVNConfigVO svncfgVO, String svnDestDir) {
		logger.info("------------------------svn checkout begin...----------------------");
		int ret = -1;
		// 登录svn服务器
		SVNClientManager clientManager = SvnKitUtil.authSvn(
				svncfgVO.getSvnDir(), svncfgVO.getSvnUserName(),
				svncfgVO.getSvnPassword());

		SVNURL svnUrl;
		clientManager.setEventHandler(new UpdateEventHandler());
		// checkout代码,指定svn下载路径，下载保存路径
		try {
			svnUrl = SVNURL.parseURIDecoded(svncfgVO.getSvnDir());
			Long res = SvnKitUtil.checkout(clientManager, svnUrl,
					SVNRevision.HEAD, new File(svnDestDir), SVNDepth.INFINITY);
			logger.info(res);

		} catch (SVNException e) {
			logger.error(e);
		}

		return ret;

	}
	@Override
	public int svnUpdate(SVNConfigVO svncfgVO, String svnDestDir) {
		logger.info("------------------------svn udpate begin...----------------------");
		int ret = -1;
		// 登录svn服务器
		SVNClientManager clientManager = SvnKitUtil.authSvn(
				svncfgVO.getSvnDir(), svncfgVO.getSvnUserName(),
				svncfgVO.getSvnPassword());
		clientManager.setEventHandler(new UpdateEventHandler());
		// update 代码
		Long res = SvnKitUtil.update(clientManager, new File(svnDestDir), SVNRevision.HEAD, SVNDepth.INFINITY);
		logger.info("svn update res: "+res);
		
		return ret;
		
	}


	public int warBuildAndDistribute(final SourceHostVO sourceHostVO) {
		
		Runnable task = new Runnable() {
			@Override
			public void run() {
				
				try {
					Thread.sleep(2000);
				} catch (InterruptedException e1) {
					logger.error(e1);
				}
				// svnDestDir暂时使用常量,因为mvn脚本目前是写死的。
				String svnDestDir = ServiceDeployConfigConstant.SVN_DOWNLOAD_DIR;
				File file = new File(svnDestDir);
				if(null != file.listFiles() && file.listFiles().length != 0) {
					// svn更新
					svnUpdate(sourceHostVO.getSvnVO(), svnDestDir);
				} else {
					// svn检出
					svnCheckOut(sourceHostVO.getSvnVO(), svnDestDir);
				}
				
				// 打包 target
				mvnBuild(sourceHostVO);
				
				// copy war 目录
				FileMoveOrCopyVO fileMove = new FileMoveOrCopyVO();
				fileMove.setDestDir(ServiceDeployConfigConstant.WORKDIR);
				fileMove.setSourceDir(ServiceDeployConfigConstant.WAR_TARGET_DIR);
				fileMove.setDestFileName(sourceHostVO.getWarName()+".war");
				fileMove.setSourceFileName(sourceHostVO.getWarName()+".war");
				// 切包备份目录
				FileMoveOrCopyVO fileBackup = new FileMoveOrCopyVO();
				fileBackup.setSourceDir(ServiceDeployConfigConstant.DEF_BUCKUP_DIR);
				fileBackup.setSourceFileName(sourceHostVO.getWarName()+".war");
				fileBackup.setDestFileName(sourceHostVO.getWarName()+".war");
				
				// 遍历分发服务器
				List<SourceHostVO> sourceHost = new ArrayList<SourceHostVO>();
				sourceHost.add(sourceHostVO);
				if(BaseUtil.listNotNull(sourceHostVO.getDests())) {
					for(DestinationHostVO dest : sourceHostVO.getDests()) {
						List<DestinationHostVO> dests = new ArrayList<DestinationHostVO>();
						dests.add(dest);
						// copy war包
						copyFile(sourceHostVO, fileMove);
						// 解压缩
						File warFile = new File(fileMove.getDestDir() + fileMove.getDestFileName());
						WarUtil.unzipWar(warFile, ServiceDeployConfigConstant.WORKDIR);
						// 替换配置文件
						WarUtil.replaceFile(dest.getCfgs());
						// 压缩
						WarUtil.zip(ServiceDeployConfigConstant.WORKDIR + sourceHostVO.getWarName() + "/", ServiceDeployConfigConstant.WORKDIR);
						// 停止web容器
						stopService(dests);
						// 分发
						// -- 备份路径
						fileBackup.setSourceDir(fileBackup.getSourceDir()+ DateUtil.dateToFormatString(new Date()) + "/");
						// -- 分发webapp路径
						fileBackup.setDestDir(dest.getWebappPath()+"/");
						// -- 创建备份目录
						makedir(dest, fileBackup.getSourceDir());
						// -- 删除webapps war
						removeFile(dest, dest.getWebappPath() + "/" + sourceHostVO.getWarName());
						removeFile(dest, dest.getWebappPath() + "/" + sourceHostVO.getWarName() + ".war");
						try {
							distributeWar(dest, fileBackup, sourceHostVO.getWarName()+".war");
						} catch (IOException e) {
							logger.error(e);
						}
						// 切包
						switchWar(dest, fileBackup);
						// 启动web容器
						startService(dests);
						
					}
				}
			}};
			executor.execute(task);
			return 1;

	}

	@Override
	public int startService(List<DestinationHostVO> serverHosts) {
		logger.info("------------------------start service...----------------------");
		int ret = -1;
		for (DestinationHostVO server : serverHosts) {
			try {
				ret = SSHExecUtil.runSSH(server.getHostIp(),
						server.getUserName(), server.getPassWord(),
						server.getStartUpPath());
				logger.info("SSH call [start service] result is:" + ret);
			} catch (IOException e) {
				logger.error(e);
			}
		}
		return ret;

	}

	@Override
	public int stopService(List<DestinationHostVO> serverHosts) {
		logger.info("------------------------stop service...----------------------");
		int ret = -1;
		for (DestinationHostVO server : serverHosts) {
			try {
				ret = SSHExecUtil.runSSH(server.getHostIp(),
						server.getUserName(), server.getPassWord(),
						server.getShutDownPath());
				logger.info("SSH call [stop service] result is:" + ret);
			} catch (IOException e) {
				logger.error(e);
			}
		}
		return ret;
	}

	@Override
	public int switchWar(HostAccessVO destVO, FileMoveOrCopyVO fileMoveOrCopyVO) {
		logger.info("------------------------switch war begin...----------------------");
		int ret = -1;
		try {
			ret = SSHExecUtil.runSSH(
					destVO.getHostIp(),
					destVO.getUserName(),
					destVO.getPassWord(),
					"ln -s " + fileMoveOrCopyVO.getSourceDir() + fileMoveOrCopyVO.getSourceFileName() + " "
							+ fileMoveOrCopyVO.getDestDir()	+ fileMoveOrCopyVO.getDestFileName());
			logger.info("SSH call [switch war] result is:" + ret);
		} catch (IOException e) {
			logger.error(e);
		}
		
		return ret;
	}

	/************************************* unexposive method **********************************************/

	private int mvnBuild(HostAccessVO hostAccessVO) {
		logger.info("------------------------mvn build begin...----------------------");
		int ret = -1;
		try {
			ret = SSHExecUtil.runSSH(hostAccessVO.getHostIp(),
					hostAccessVO.getUserName(), hostAccessVO.getPassWord(),
					ServiceDeployConfigConstant.SHELL_DIR + "mvn-build.sh");
			logger.info("SSH call [mvn-build] result is:" + ret);
		} catch (IOException e) {
			logger.error(e);
		}
		return ret;
	}

	/**
	 * @Description 将处理完的包分发到指定服务器的备份目录下
	 * @param serverHosts
	 * @return
	 * @throws IOException
	 * @author xuchao
	 * @date 2015-5-27 下午2:14:07
	 */
	@Override
	public int distributeWar(DestinationHostVO server, FileMoveOrCopyVO backUpVO, String warName) throws IOException {
		int ret = 0;
		logger.info("------------------------Distribute package from Sourcehost to Desthost...----------------------");
		if (null == server.getBackupDir()) {
			server.setBackupDir(backUpVO.getSourceDir());
		}
		SSHExecUtil.scpPut(server.getHostIp(), server.getUserName(),
				server.getPassWord(), ServiceDeployConfigConstant.WORKDIR + warName,
				server.getBackupDir());
		return ret;

	}

	/**
	 * @Description copy文件
	 * @param hostAccessVO
	 * @param fileMoveOrCopyVO
	 * @return
	 * @author xuchao
	 * @date 2015-5-27 下午2:56:20
	 */
	@Override
	public int copyFile(HostAccessVO hostAccessVO,
			FileMoveOrCopyVO fileMoveOrCopyVO) {
		logger.info("------------------------copy file...----------------------");
		int ret = -1;
		try {
			ret = SSHExecUtil.runSSH(hostAccessVO.getHostIp(),
					hostAccessVO.getUserName(), hostAccessVO.getPassWord(),
					// TODO shell加参数化处理
					ServiceDeployConfigConstant.SHELL_DIR + "copyfile.sh "
							+ fileMoveOrCopyVO.getSourceDir() + " "
							+ fileMoveOrCopyVO.getSourceFileName() + " "
							+ fileMoveOrCopyVO.getDestDir() + " "
							+ fileMoveOrCopyVO.getDestFileName());
			logger.info("SSH call [copy fille] result is:" + ret);
		} catch (IOException e) {
			logger.error(e);
		}
		return ret;
	}

	/**
	 * @Description 移动文件
	 * @param hostAccessVO
	 * @param fileMoveOrCopyVO
	 * @return
	 * @author xuchao
	 * @date 2015-5-27 下午2:56:35
	 */
	@Override
	public int moveFile(HostAccessVO hostAccessVO, FileMoveOrCopyVO fileMoveOrCopyVO) {
		logger.info("------------------------move file...----------------------");
		int ret = -1;
		try {
			ret = SSHExecUtil.runSSH(hostAccessVO.getHostIp(),
					hostAccessVO.getUserName(), hostAccessVO.getPassWord(),
					// TODO shell加参数化处理
					ServiceDeployConfigConstant.SHELL_DIR + "mvfile.sh "
							+ fileMoveOrCopyVO.getSourceDir() + " "
							+ fileMoveOrCopyVO.getSourceFileName() + " "
							+ fileMoveOrCopyVO.getDestDir() + " "
							+ fileMoveOrCopyVO.getSourceFileName());
			logger.info("SSH call [move file] result is:" + ret);
		} catch (IOException e) {
			logger.error(e);
		}
		return ret;
	}

	@Override
	public int makedir(HostAccessVO hostAccessVO, String pathFolderName) {
		logger.info("------------------------mkdir-------------------------");
		int ret = -1;
		try {
			ret = SSHExecUtil.runSSH(hostAccessVO.getHostIp(),
					hostAccessVO.getUserName(), hostAccessVO.getPassWord(),
					"mkdir " + pathFolderName);
			logger.info("mkdir " + pathFolderName);
			logger.info("SSH call [mkdir] result is:" + ret);
		} catch (IOException e) {
			logger.error(e);
		}
		return ret;
	}
	private int removeFile(HostAccessVO hostAccessVO, String pathFolderName) {
		logger.info("------------------------rm-------------------------");
		int ret = -1;
		try {
			ret = SSHExecUtil.runSSH(hostAccessVO.getHostIp(),
					hostAccessVO.getUserName(), hostAccessVO.getPassWord(),
					"rm -rf " + pathFolderName);
			logger.info("mkdir " + pathFolderName);
			logger.info("SSH call [mkdir] result is:" + ret);
		} catch (IOException e) {
			logger.error(e);
		}
		return ret;
	}

	@Override
	public int tailf(final HostAccessVO hostAccessVO, final String dirAndFileName, final int tailLines) {
		// 异步执行
		Runnable task = new Runnable() {
			
			@Override
			public void run() {
				logger.info("---------------------tail log begin------------------");
				int ret = -1;
				try {
					ret = SSHExecUtil.runSSH(hostAccessVO.getHostIp(), hostAccessVO.getUserName(), 
							hostAccessVO.getPassWord(),ServiceDeployConfigConstant.SHELL_DIR +
							"tailf.sh"+" "+tailLines+" "+dirAndFileName);
					logger.info("SSH call [tailf] result is:" + ret);
				} catch (IOException e) {
					logger.error("", e);
				}
				
			}
		};
		executor.execute(task);
		return 1;
	}

}
